﻿using System;
using NLog;
using NLog.Targets;
using System.Collections;
using System.Collections.Generic;

namespace NewsMine.Logging
{
    public class NewsMineLogger : INewsMineLogger
    {        
        
        /// <summary>
        /// The NLog logger which this class wraps.
        /// </summary>
        private Logger logger;

        /// <summary>
        /// Constructs an instance of 
        /// by wrapping a NLog logger
        /// </summary>
        /// <param name="logger">The NLog logger to wrap</param>
        internal NewsMineLogger(Logger logger)
        {
          this.logger = logger;
        }

        public bool IsDebugEnabled { get { return logger.IsDebugEnabled; } }
        public bool IsErrorEnabled { get { return logger.IsErrorEnabled; } }
        public bool IsFatalEnabled { get { return logger.IsFatalEnabled; } }
        public bool IsInfoEnabled { get { return logger.IsInfoEnabled; } }
        public bool IsTraceEnabled { get { return logger.IsTraceEnabled; } }
        public bool IsWarnEnabled { get { return logger.IsWarnEnabled; } }
        


        public void Debug(string message, IDictionary<object, object> properties=null)
        {
            if (logger.IsDebugEnabled)
                Write(LogLevel.Debug, message,properties,null);                
        }


        public void DebugException(string message, Exception ex, IDictionary<object, object> properties=null)
        {
            if (logger.IsDebugEnabled)
                Write(LogLevel.Debug, message, properties, ex);
        }

        public void ErrorException(string message, Exception ex, IDictionary<object, object> properties = null)
        {
            if (logger.IsErrorEnabled)
                Write(LogLevel.Error, message,properties, ex);
        }

        public void Error(string message, IDictionary<object, object> properties = null)
        {
            if (logger.IsErrorEnabled)
                Write(LogLevel.Error, message, properties);
        }

        public void Fatal(string message, IDictionary<object, object> properties = null)
        {
            if (logger.IsFatalEnabled)
                Write(LogLevel.Fatal, message, properties);
        }

        public void FatalException(string message, Exception ex, IDictionary<object, object> properties = null)
        {
            if (logger.IsFatalEnabled)
                Write(LogLevel.Fatal, message, properties, ex);
        }

        public void Info(string message, IDictionary<object, object> properties = null)
        {
            if (logger.IsInfoEnabled)
                Write(LogLevel.Info, message, properties);
        }

        public void InfoException(string message, Exception ex, IDictionary<object, object> properties = null)
        {
            if (logger.IsInfoEnabled)
                Write(LogLevel.Info, message, properties, ex);
        }


        public void Trace(string message, IDictionary<object, object> properties = null)
        {
            if (logger.IsTraceEnabled)
                Write(LogLevel.Trace, message, properties);
        }

        public void TraceException(string message, Exception ex, IDictionary<object, object> properties = null)
        {
            if (logger.IsTraceEnabled)
                Write(LogLevel.Trace, message, properties, ex);
        }

        public void Warn(string message, IDictionary<object, object> properties = null)
        {
            if (logger.IsWarnEnabled)
                Write(LogLevel.Warn, message,properties);
        }

        public void WarnException(string message, Exception ex, IDictionary<object, object> properties = null)
        {
            if (logger.IsWarnEnabled)
                Write(LogLevel.Warn, message, properties, ex);
        }

        private void Write(LogLevel level, string message, IDictionary<object,object> properties=null, Exception ex=null, params object[] args)
        {
            LogEventInfo logEventInfo = new LogEventInfo(level, logger.Name, null, message, args, ex);

            if (properties == null) 
                properties = new Dictionary<object, object>();
            
            properties["SessionId"] = NewsMineLogManager.SessionId ?? "-";
            
            foreach (var property in properties)
            {
                logEventInfo.Properties.Add(property.Key, property.Value);
            }
            logger.Log(typeof(NewsMineLogger), logEventInfo);
        }

        public string GetLogFilePath(string fileTargetName)
        {

            dynamic standardTarget = LogManager.Configuration.FindTargetByName(fileTargetName);
            string expandedFileName;
            string fileName = expandedFileName = string.Empty;

            if (standardTarget != null)
            {

                if (standardTarget.GetType() == typeof(NLog.Targets.Wrappers.AsyncTargetWrapper))
                {                    
                    fileName = ((FileTarget)(standardTarget.WrappedTarget)).FileName.ToString();
                }
                else if (standardTarget.GetType() == typeof(FileTarget))
                {
                    fileName = standardTarget.FileName.ToString();
                }

                if (!string.IsNullOrEmpty(fileName))
                    expandedFileName = NLog.Layouts.SimpleLayout.Evaluate(fileName);
                else
                    return fileName;

                // paths like c:\test\/myLogfiles/Log.txt are handled correctly
                return expandedFileName.Replace("/", "\\").Replace("\\\\", "\\");
                
            }
            
            return string.Empty;
            
        }

    }
}
